﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;

namespace Common.Standard
{
    public static class StringHelper
    {
        /// <summary>
        /// 生成随机码
        /// </summary>
        /// <param name="type"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public static string RandCode(int length = 6, RandCodeType type = RandCodeType.Number)
        {
            if (length < 1)
            {
                throw new Exception("长度错误");

            }
            StringBuilder sb = new StringBuilder(length);
            switch (type)
            {
                case RandCodeType.Word:
                    {
                        for (int i = 0; i < length; i++)
                        {

                            Random rand = new Random((int)DateTime.Now.Ticks + i);
                            Random rand_num = new Random((int)DateTime.Now.Ticks + i);
                            var number = rand_num.Next(10000) % 26;
                            var seed = rand.Next(1000);
                            var ch = 'a';
                            if (seed % 2 == 0)
                            {
                                ch = (char)('a' + number);

                            }
                            else
                            {
                                ch = (char)('A' + number);
                            }
                            sb.Append(ch.ToString());

                        }
                    }
                    break;
                case RandCodeType.Mix:
                    {
                        for (int i = 0; i < length; i++)
                        {

                            Random rand = new Random((int)DateTime.Now.Ticks + i);
                            Random rand_num = new Random((int)DateTime.Now.Ticks + i);
                            var current_randnubmer = rand_num.Next(10000);
                            var number = current_randnubmer % 26;
                            var seed = rand.Next(1000);
                            var ch = 'a';
                            var flag = seed % 3;
                            if (flag == 0)
                            {
                                ch = (char)('a' + number);

                            }
                            else if (flag == 1)
                            {
                                ch = (char)('A' + number);
                            }
                            else
                            {
                                ch = (char)('0' + current_randnubmer % 10);
                            }
                            sb.Append(ch.ToString());

                        }
                    }
                    break;
                default:
                    {

                        for (int i = 0; i < length; i++)
                        {
                            Random rand = new Random((int)DateTime.Now.Ticks + i);
                            var num = rand.Next(10000) % 10;
                            sb.Append(num);
                        }
                    }

                    break;
            }
            return sb.ToString();
        }
        public static int timeToStamp(DateTime time)
        {
            return (int)(TimeZoneInfo.ConvertTimeToUtc(time) - TimeZoneInfo.ConvertTimeToUtc(new System.DateTime(1970, 1, 1))).TotalSeconds-8*3600;
        }
        public static string timeToStamp11(DateTime time)
        {
            return ((TimeZoneInfo.ConvertTimeToUtc(time) - TimeZoneInfo.ConvertTimeToUtc(new System.DateTime(1970, 1, 1))).TotalMilliseconds - 8 * 3600*1000).ToString();
        }
        /// <summary>
        /// 10位转时间
        /// </summary>
        /// <param name="stamp"></param>
        /// <returns></returns>
        public static DateTime stampToTime(int stamp)
        {
            DateTime dtStart = TimeZoneInfo.ConvertTimeToUtc(new DateTime(1970, 1, 1));
            return new DateTime(1970, 1, 1).AddSeconds(stamp+ 8 * 3600);
        }

        /// <summary>
        /// 字符串小写MD5加密
        /// </summary>
        /// <param name="str">要加密的字符串</param>
        /// <returns>加密后的字符串</returns>
        public static string ToMD5(this string str)
        {
            MD5 md5Hash = MD5.Create();
            byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(str));
            StringBuilder sBuilder = new StringBuilder();
            for (int i = 0; i < data.Length; i++)
            {
                sBuilder.Append(data[i].ToString("x2"));
            }
            return sBuilder.ToString().ToUpper();
        }

        #region 把时间戳转换成日期
        /// <summary>
        /// 时间戳转为C#格式时间
        /// </summary>
        /// <param name="timeStamp">Unix时间戳格式</param>
        /// <returns>C#格式时间</returns>
        public static DateTime ToDateTime(this string timeStamp)
        {
            DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            long lTime = long.Parse(timeStamp + "0000000");
            TimeSpan toNow = new TimeSpan(lTime);
            return dtStart.Add(toNow);
        }


        #endregion

        #region 把日期转换成Unix时间戳


        /// <summary>
        /// DateTime时间格式转换为Unix时间戳格式
        /// </summary>
        /// <param name="time"> DateTime时间格式</param>
        /// <returns>Unix时间戳格式</returns>
        public static string ToTimestamp(this System.DateTime time)
        {
            System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));
            return Math.Ceiling((time - startTime).TotalMilliseconds).ToString();
        }
        #endregion

        #region 将对象属性转换为Key-Value键值对

        /// <summary>
        /// 将对象属性转换为Key-Value键值对
        /// </summary>
        /// <param name="o"></param>
        /// <returns></returns>
        public static Dictionary<string, object> Object2Dictionary(this object o)
        {
            Dictionary<string, object> map = new Dictionary<string, object>();

            Type t = o.GetType();

            PropertyInfo[] pi = t.GetProperties(BindingFlags.Public | BindingFlags.Instance);

            foreach (PropertyInfo p in pi)
            {
                MethodInfo mi = p.GetGetMethod();

                if (mi != null && mi.IsPublic)
                {
                    map.Add(p.Name, mi.Invoke(o, new object[] { }));
                }
            }
            return map;
        }

        #endregion 将对象属性转换为Key-Value键值对

        #region 把对象类型转换成指定的类型，转化失败时返回指定默认值

        /// <summary>
        /// 把对象类型转换成指定的类型，转化失败时返回指定默认值
        /// </summary>
        /// <typeparam name="T">动态类型</typeparam>
        /// <param name="value">要转换的原对象</param>
        /// <param name="detaultValue">转换失败时返回的默认值</param>
        /// <returns>转化后指定类型对象，转化失败时返回指定默认值</returns>
        public static T CastTo<T>(this object value, T detaultValue)
        {
            object result;
            Type t = typeof(T);
            try
            {
                result = t.IsEnum ? System.Enum.Parse(t, value.ToString()) : Convert.ChangeType(value, t);
            }
            catch (Exception)
            {
                return detaultValue;
            }

            return (T)result;
        }

        #endregion 把对象类型转换成指定的类型，转化失败时返回指定默认值

        #region 把对象类型转换成指定的类型，转化失败时返回类型默认值

        /// <summary>
        /// 把对象类型转换成指定的类型，转化失败时返回类型默认值
        /// </summary>
        /// <typeparam name="T">动态类型</typeparam>
        /// <param name="value">要转换的原对象</param>
        /// <returns>转化后指定类型对象，转化失败时返回类型默认值</returns>
        public static T CastTo<T>(this object value)
        {
            object result;
            Type t = typeof(T);
            try
            {
                if (t.IsEnum)
                {
                    result = System.Enum.Parse(t, value.ToString());
                }
                else if (t == typeof(Guid))
                {
                    result = Guid.Parse(value.ToString());
                }
                else
                {
                    result = Convert.ChangeType(value, t);
                }
            }
            catch (Exception)
            {
                result = default(T);
            }

            return (T)result;
        }

        #endregion 把对象类型转换成指定的类型，转化失败时返回类型默认值
    }

    public enum RandCodeType
    {
        /// <summary>
        /// 数字
        /// </summary>
        Number = 1,
        /// <summary>
        /// 字母
        /// </summary>
        Word = 2,
        /// <summary>
        /// 数字，字母混合
        /// </summary>
        Mix = 3
    }
}
